package Ex2;

import java.util.LinkedHashSet;
import java.util.Set;



public class MyGraph 
{
	private static Set <Vertex> vertices;
	private static Set <Edge> edges;
	
	MyGraph()
	{
		vertices = new  LinkedHashSet<Vertex>();
		edges = new  LinkedHashSet<Edge>();
	}
	
	public Set<Vertex> getVertices()
	{
		return vertices;
	}
	
	public Set<Vertex> getIncomingVertices(Vertex v)
	{
		Set <Vertex> neighbors = new LinkedHashSet<Vertex>();
		for (Edge e : edges) 
		{
			Vertex u1 = e.getVertex(1);
			Vertex u2 = e.getVertex(2);
			if(u2.equals(v))
			{
				neighbors.add(u1);
			}
		}
		
		return neighbors;
	}
	
	public Set<Edge> getEdges()
	{
		return edges;
	}

	private int addVertex(Vertex v)
	{
		
		if (vertices.contains(v))
		{
			
			Vertex.nVertices--;
			return 0;  
		}
		
		vertices.add(v);
		
		return v.id;
	}
	
	public int addVertex(String val)
	{
		Vertex v = new Vertex(val);
		return addVertex(v);
	}
	
	public boolean isVertexExists(String val)
	{
		return (getVertex(val) == null) ? false : true;
	}
	
	private Vertex getVertex(String val)
	{
		for (Vertex v : vertices) 
		{
			if (v.value.equals(val)) return v;
		}
		
		return null;
	}
	
	public void addEdge(String val1, String val2)
	{	
		Vertex v1 = getVertex(val1);
		Vertex v2 = getVertex(val2);
		
		Edge e = new Edge(v1, v2);
		if (edges.contains(e))
		{
			Edge.nEdges--;
			return;
		}
		
		edges.add(e);
	}
	
	public void print()
	{
		System.out.println("vertices:");
		for (Vertex v : vertices) 
		{
			v.printVertex();
		}
		
		System.out.println("\nedges:");
		for (Edge e : edges) 
		{
			e.printEdge();		
		}	
	}
	
	public static class Vertex
	{
		private static int nVertices = 0;
		private int id;
		private String value;
		
		Vertex(String val)
		{
			this.id = ++nVertices;
			this.value = val;
		}
		
		public String getValue()
		{
			return this.value;
		}
		
		public void printVertex()
		{
			System.out.println(this.id + ") "  + this.value);
		}
		
		public boolean equals(Object o)
		{
			return (((Vertex)o).getValue().equals(this.value));
		}
		
		public int hashCode()
		{
			return 17;
		}
		
		public String toString()
		{
			return this.id + ": "+this.value;
		}
	}
	
	
	public static class Edge
	{
		private static int nEdges = 0;
		private int id;
		private Vertex v1;
		private Vertex v2;
		
		Edge(Vertex v1, Vertex v2)
		{
			this.id = ++nEdges;
			this.v1 = v1;
			this.v2 = v2;
		}
		
		public Vertex getVertex(int i)
		{
			if (i == 1) return v1;
			
			if (i == 2) return v2;
			
			return null;
		}
		
		public String getVertexValue(int i)
		{
			if (i == 1) return v1.getValue();
			
			if (i == 2) return v2.getValue();
			
			return "";
		}
		
		public void printEdge()
		{
			System.out.println(this.id + ") '" + v1.getValue() + "' -> '" + v2.getValue() + "'");
		}
		
		public boolean equals(Object o)
		{
			return (this.getVertexValue(1).equals(((Edge)o).getVertexValue(1)) && this.getVertexValue(2).equals(((Edge)o).getVertexValue(2)));
		}
		
		public int hashCode()
		{
			return 7;
		}
		
	}
	
}
